package com.projles.minigames;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import com.projles.release1.R;
import com.projles.release1.TelaAvisoActivity;
import com.projles.util.Expressao;
import com.projles.util.Jogador;
import com.projles.util.Player;

public class MiniGameCalculadoraActivity extends Activity {

	private Random gerador = new Random();
    private Expressao expressaoGerada = null;
    private final Integer NUM_RODADAS = 3;
    private final long TEMPO_LIMITE_PARA_RESPONDER = 10000; //em milisegundos

    private List<Jogador> jogadores = new ArrayList<Jogador>();

    private Integer indiceJogadorAtual;
    private Jogador jogadorAtual;
    
    private CountDownTimer countdown;
    private TextView countdownView;
    private EditText entrada;
    private TextView saudacao;
    private TextView status;
    private TextView expressao;
    private View viewParaAnimar;
    
    private Player player;
    
    @SuppressWarnings("unchecked")
	@Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.minigame_calculadora);
    	
    	player = Player.getPlayer(this);

    	//Pegando os parametros da Intent passados na Activity anterior
    	Bundle params = getIntent().getExtras();
    	
    	jogadores = (ArrayList<Jogador>) params.get("jogadores");
    	indiceJogadorAtual = -1;
    	atualizarJogadorAtual();
    	
    	limpaPontuacaoJogadores();
    	
    	countdownView = (TextView) findViewById(R.id.countdown_calculadora);
    	saudacao = (TextView) findViewById(R.id.saudacao);
    	status = (TextView) findViewById(R.id.status);
    	expressao = (TextView) findViewById(R.id.expressao);
    	entrada = (EditText) findViewById(R.id.resultado);
    	viewParaAnimar = findViewById(R.id.layout_mais_externo);

       	countdown = new CountDownTimer(TEMPO_LIMITE_PARA_RESPONDER, 500) {
			
    			@Override
    			public void onTick(long tempoRestante) {
    				countdownView.setText("Tempo: " + tempoRestante/1000);
    				if (tempoRestante/1000 < 4) {
    					countdownView.setTextColor(Color.RED);
    				}
    			}
    			
    			@Override
    			public void onFinish() {
    				
    				jogadorAtual.errou();
    				player.doh();
    				
    				// mostrando que o seu tempo acabou
    				Intent i = new Intent(MiniGameCalculadoraActivity.this, TelaAvisoActivity.class);
    				i.putExtra("status_tela", TelaAvisoActivity.FIM_TEMPO);
    				startActivity(i);
    				
    				novaRodada();
    			}
    		};
    		
    	entrada.setOnKeyListener(new OnKeyListener() {
        	@Override
        	public boolean onKey(View v, int keyCode, KeyEvent event) {
                // O usuario apertar Enter no nosso EditText
                if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {

                	if (entrada.getText().length() == 0) {
                		return false;
                	}
                	
                	
                	if (usuarioAcertou(entrada)) {
                	  jogadorAtual.acertou();
                	  player.excellent();
                	  
                	  // tela splash avisando que o jogador acertou
                	  Intent i = new Intent(MiniGameCalculadoraActivity.this, TelaAvisoActivity.class);
                	  i.putExtra("status_tela", TelaAvisoActivity.ACERTOU);
                	  startActivity(i);
                	  
                	} else {
                	  jogadorAtual.errou();
                	  player.doh();
                	  
                	  // tela splash avisando que o jogador errou                	  
                	  Intent i = new Intent(MiniGameCalculadoraActivity.this, TelaAvisoActivity.class);
                	  i.putExtra("status_tela", TelaAvisoActivity.ERROU);
                	  startActivity(i);
                	  
                	}
              	  	novaRodada();
                	return true;
                }
                return false;
        	}
    	});
    	
    }
    
    @Override
    public void onStop() {
    	super.onStop();
    	countdown.cancel();
    }

    
    @Override
	public void onConfigurationChanged(Configuration newConfig) {
	  // ignore orientation/keyboard change
	  super.onConfigurationChanged(newConfig);
	}
    

	
    @Override
    public void onStart() {
    	super.onStart();

    	animarEntradaView();
    	
    	Expressao expressaoGerada = gerarExpressaoAleatoria();
    	
    	countdownView.setTextColor(Color.WHITE);
    	saudacao.setText("Sua vez, " + jogadores.get(indiceJogadorAtual).getNome());
    	status.setText("Erros: " + jogadorAtual.getErros() + "  Acertos: " + jogadorAtual.getAcertos());
    	expressao.setText(expressaoGerada.toString() + " = ");
    	entrada.setText("");
    	countdown.start();
    	
    }
    
    private void limpaPontuacaoJogadores() {
		
    	for(Jogador j : jogadores) {
    		j.zerarErrosAcertos();
    	}
	}
    
    private void atualizarJogadorAtual() {
    	if (indiceJogadorAtual == jogadores.size() - 1) {
    		indiceJogadorAtual = 0;
    	} else {
    		indiceJogadorAtual++;
    	}
    	
    	jogadorAtual = jogadores.get(indiceJogadorAtual);
    }
    
    private void novaRodada() {
    	esconderTeclado();
    	
    	if (!terminou()) {
    		atualizarJogadorAtual();
    		onStart();
      	} else {
      		
      		resultadoJogo();
      		
      		// retornando a lista de jogadores atualizada
      		Intent i = this.getIntent();
      		i.putExtra("listaAtualizada", (Serializable) jogadores);
      		this.setResult(RESULT_OK, i);

      		finish();
    	}
    }
    
    
	private boolean terminou() {
    	if (jogadorAtual.equals(jogadores.get(jogadores.size() - 1))) {
    		Integer numRodadas = jogadorAtual.getAcertos() + jogadorAtual.getErros();
    		
    		//Se o ultimo jogador da sequencia tiver jogado NUM_RODADAS vezes
    		if (numRodadas == NUM_RODADAS) {
    			return true; 
    		}
    	}
    	return false;
    }
    
	private void esconderTeclado() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(entrada.getWindowToken(), 0);
	}

    private void animarEntradaView() {
    	Animation in = AnimationUtils.makeInChildBottomAnimation(this);
    	viewParaAnimar.startAnimation(in);
    	viewParaAnimar.setVisibility(View.VISIBLE);
	}
    
    private void resultadoJogo(){
    	
    	boolean empate = false;
    	
    	Jogador jogadorQueErrouMais = jogadores.get(0);
    	
    	for (int i = 1; i < jogadores.size(); i++) {

    		Jogador j = jogadores.get(i); 
    		
    		if (j.getErros() > jogadorQueErrouMais.getErros()) {
    			empate = false;
    			jogadorQueErrouMais = j;
    		}
    		else if (j.getErros() == jogadorQueErrouMais.getErros()) {
    			empate = true;
    		}
			
		}
    	
    	
    	if (empate) {

    		// tela splash avisando que o jogador errou                	  
    		final Intent splash = new Intent(MiniGameCalculadoraActivity.this, TelaAvisoActivity.class);
    		splash.putExtra("status_tela", TelaAvisoActivity.EMPATOU);

    		// adicionando um dalay para q o resultado parcial aparece antes do final
    		Handler handler = new Handler(); 
    	    handler.postDelayed(new Runnable() { 
    	         public void run() { 
    	        	 startActivity(splash);
    	         } 
    	    }, 2000); 
    	}
    	else {
    		jogadorQueErrouMais.addDerrota();
    		
    		// tela splash avisando que o jogador errou                	  
    		final Intent splash = new Intent(MiniGameCalculadoraActivity.this, TelaAvisoActivity.class);
    		splash.putExtra("status_tela", TelaAvisoActivity.ACABOU);
    		splash.putExtra("jogador", (Serializable) jogadorQueErrouMais);

    		player.aplausos();
    		// adicionando um dalay para q o resultado parcial aparece antes do final
    		Handler handler = new Handler(); 
    	    handler.postDelayed(new Runnable() { 
    	         public void run() { 
    	        	 startActivity(splash);
    	         } 
    	    }, 1500); 
    		
    	}
    
    	
    	
    }
    
    private Integer divisorInteiro(Integer numerador) {
    	List<Integer> divisores = new ArrayList<Integer>();
    	
    	if (numerador == 0) {
    		Integer numeroGerado = gerador.nextInt(100);
    		while (numeroGerado == 0) {
    			numeroGerado = gerador.nextInt(100);
    		}
    		return numeroGerado;
    	}
    	
    	for (int i = 1; i <= numerador; i++) {
    		if (numerador % i == 0) {
    			divisores.add(i);
    		}
    	}
    	
    	return divisores.get(gerador.nextInt(divisores.size()));
    }
    
    private Expressao gerarExpressaoAleatoria() {
    	String operacaoAleatoria = "";
    	
    	Integer numeroAleatorio1;
    	Integer numeroAleatorio2;
    	Integer resultado;
    	
    	switch (gerador.nextInt(65536) % 4) {
    	case 0: 
    		operacaoAleatoria = "+";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = gerador.nextInt(100);
    		resultado = numeroAleatorio1 + numeroAleatorio2;
    		break;
    	case 1:
    		operacaoAleatoria = "-";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = gerador.nextInt(100);
    		resultado = numeroAleatorio1 - numeroAleatorio2;
    		break;
    	case 2:
    		operacaoAleatoria = "*";
    		numeroAleatorio1 = gerador.nextInt(10);
    		numeroAleatorio2 = gerador.nextInt(10);
    		resultado = numeroAleatorio1 * numeroAleatorio2;
    		break;
    	default:
    		operacaoAleatoria = "/";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = divisorInteiro(numeroAleatorio1);
    		resultado = numeroAleatorio1 / numeroAleatorio2;
    		break;
    	}
    	
    	expressaoGerada = new Expressao(numeroAleatorio1, operacaoAleatoria, numeroAleatorio2);
    	expressaoGerada.setResultado(resultado);
    	return expressaoGerada;
    }
    
    private boolean usuarioAcertou(EditText entrada) {
    	Integer chute = Integer.valueOf(entrada.getText().toString());
    	Integer valorExpressao = expressaoGerada.getResultado();
    	
    	if (chute.equals(valorExpressao)) {
    		return true;
    	}
    	return false;
    }
}